package com.polaris.live.im.sfs.core

import com.polaris.live.common.util.JsonUtils
import com.polaris.live.common.util.LogExt
import com.polaris.live.common.util.associateNotNull
import com.polaris.live.im.sfs.ARGUMENTS_CLIENT_TYPE
import com.polaris.live.im.sfs.ARGUMENTS_PARAMS
import com.polaris.live.im.sfs.REQUEST_HEARTBEAT
import com.polaris.live.im.sfs.core.bean.DataArgument
import com.polaris.live.im.sfs.interfaces.OnImMessageListener
import com.polaris.live.im.sfs.processor.InterruptMessageProcessSignal
import com.polaris.live.im.sfs.processor.MessageProcessor
import com.polaris.live.im.sfs.processor.impl.AccountChangeMessageProcessor
import com.polaris.live.im.sfs.processor.impl.CallEventMessageProcessor
import com.polaris.live.im.sfs.processor.impl.GameAccountChangeMessageProcessor
import com.polaris.live.im.sfs.processor.impl.GameResultMessageProcessor
import com.polaris.live.im.sfs.processor.impl.LevelAccountChangeMessageProcessor
import com.polaris.live.im.sfs.processor.impl.LevelUpMessageProcessor
import com.polaris.live.im.sfs.processor.impl.LiveEventMessageProcessor
import com.polaris.live.im.sfs.processor.impl.NoticeEventMessageProcessor
import com.polaris.live.im.sfs.processor.impl.NoticeInviteMessageProcessor
import com.polaris.live.im.sfs.processor.impl.NoticeLuckyBagMessageProcessor
import com.polaris.live.im.sfs.processor.impl.NoticePopMessageProcessor
import com.polaris.live.im.sfs.processor.impl.NoticeTaskMessageProcessor
import com.polaris.live.im.sfs.processor.impl.NoticeWindowMessageProcessor
import com.polaris.live.im.sfs.processor.impl.StateChangeMessageProcessor
import com.polaris.live.im.sfs.processor.impl.UserInfoChangeMessageProcessor
import com.polaris.live.im.sfs.processor.impl.system.ExcludeMessageProcessor
import com.polaris.live.im.sfs.processor.impl.system.ExtAccountMessageProcessor
import com.polaris.live.im.sfs.processor.impl.system.PusherAckMessageProcessor
import com.polaris.live.im.utils.SmartFoxUtils
import com.smartfoxserver.v2.entities.data.SFSArray
import com.smartfoxserver.v2.entities.data.SFSObject

/**
 * 消息处理
 *
 * @author Created by lucas on 2023/10/19 10:16
 */
class MessageMediator(
    injectProcessors: List<MessageProcessor>,
) : OnImMessageListener {

    private val messageProcessors: List<MessageProcessor>

    init {
        messageProcessors =
            (injectProcessors + registerProcessors).sortedByDescending { it.order() }
    }

    override suspend fun onMessage(command: String, arguments: Map<String, Any>) {
        val type = arguments[ARGUMENTS_CLIENT_TYPE] as Int

        logMessage(type, command, arguments)

        val argument = DataArgument(command, arguments)

        messageProcessors.forEach {
            if (!it.shouldProcess(type, command)) {
                return@forEach
            }

            val signal = it.process(type, command, argument)
            if (signal is InterruptMessageProcessSignal) {
                return
            }
        }
    }

    private fun logMessage(type: Int, command: String, arguments: Map<String, Any>) {
        if (command in ignoreLogCommands) {
            return
        }

        LogExt.logJson(SmartFoxManager.TAG, {
            "${SmartFoxConnector.getName(type)}: $command eventDispatch"
        }, {
            val json = arguments.entries.associateNotNull { (k, v) ->
                if (k == "room" || k == ARGUMENTS_PARAMS) {
                    null
                } else if (v is SFSObject) {
                    k to SmartFoxUtils.flatten(v)
                } else if (v is SFSArray) {
                    k to SmartFoxUtils.flatten(v)
                } else {
                    k to v.toString()
                }
            }.let {
                JsonUtils.toJson(it)
            }

            arrayOf(json)
        })
    }

    private val ignoreLogCommands = setOf(
        REQUEST_HEARTBEAT
    )
}

private val registerProcessors = listOf<MessageProcessor>(
    ExcludeMessageProcessor(),
    ExtAccountMessageProcessor(),
    AccountChangeMessageProcessor(),
    NoticeWindowMessageProcessor(),
    NoticeEventMessageProcessor(),
    StateChangeMessageProcessor(),
    UserInfoChangeMessageProcessor(),
    CallEventMessageProcessor(),
    LiveEventMessageProcessor(),
    PusherAckMessageProcessor(),
    NoticeInviteMessageProcessor(),
    LevelUpMessageProcessor(),
    NoticeTaskMessageProcessor(),
    NoticePopMessageProcessor(),
    NoticeLuckyBagMessageProcessor(),
    GameAccountChangeMessageProcessor(),
    LevelAccountChangeMessageProcessor(),
    GameResultMessageProcessor()
)